//
//  MPBTools+Method.m
//  MPTToolsLibrary
//
//  Created by jiaxuzhou on 2017/7/20.
//  Copyright © 2017年 jxzjxz. All rights reserved.
//

#import "MPBTools+Method.h"
#import <objc/runtime.h>

static NSMutableDictionary *mdicThread;

@implementation MPBTools (Method)

+ (void)swizzleOrigSelector:(SEL)origSEL newSelector:(SEL)newSEL inClass:(Class)aclass
{
    /// 获取实例方法
    Method origMethod = class_getInstanceMethod(aclass, origSEL);
    Method newMethod = nil;
    if (!origMethod)
    {
        /// 获取静态方法
        origMethod = class_getClassMethod(aclass, origSEL);
        newMethod = class_getClassMethod(aclass, newSEL);
    }
    else
    {
        newMethod = class_getInstanceMethod(aclass, newSEL);
    }
    
    if (!origMethod||!newMethod)
    {
        return;
    }
    
    /// 自身已经有了就添加不成功，直接交换即可
    if (class_addMethod(aclass, origSEL, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
    {
        /// 添加成功一般情况是因为，origSEL本身是在c的父类里。这里添加成功了一个继承方法。
        class_replaceMethod(aclass,
                            newSEL,
                            method_getImplementation(origMethod),
                            method_getTypeEncoding(origMethod));
    }
    else
    {
        method_exchangeImplementations(origMethod, newMethod);
    }
}

+ (void)addAsyncMethod:(SEL)method target:(id)target timeInterval:(NSInteger)count repeat:(BOOL)repeat inQueue:(dispatch_queue_t)queue Mode:(NSRunLoopMode)mode
{
    NSRunLoopMode modeF = NSRunLoopCommonModes;
    if (mode)
    {
        modeF = mode;
    }
    
    dispatch_async(queue, ^
    {
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:count target:target selector:method userInfo:nil repeats:repeat];
        NSThread *thread = [NSThread currentThread];
        [thread setName:@"TimerA"];
        
        [MPBTools addStrongPropertyName:@"temp_Timer" value:timer onObj:target];
        [MPBTools addStrongPropertyName:@"temp_Thread" value:thread onObj:target];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop] run];
    });
}

+ (void)removeAsyncMethodInTarget:(id)target
{
    
    NSTimer *timer = [MPBTools getPropertyWithName:@"temp_Timer" onObj:target];
    NSThread *thread = [MPBTools getPropertyWithName:@"temp_Thread" onObj:target];

    [timer performSelector:@selector(invalidate) onThread:thread withObject:nil waitUntilDone:NO];
}

+ (void)performSelector:(SEL)aSelector onObj:(id)obj onThread:(NSString *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait
{
    if (!mdicThread)
    {
        mdicThread = [NSMutableDictionary dictionaryWithCapacity:0];
    }
    
    NSThread *thread = [mdicThread objectForKey:thr];
    if (!thread)
    {
        thread = [[NSThread alloc] initWithTarget:self selector:@selector(addRunloopForThread) object:nil];
        [thread setName:thr];
        [mdicThread setValue:thread forKey:thr];
        [thread start];
    }
    
    [obj performSelector:aSelector onThread:thread withObject:nil waitUntilDone:wait];
}

+ (void)addRunloopForThread
{
    @autoreleasepool
    {
        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
        [runLoop run];
    }
}


@end
